/*
 *  scoreBoard - PlayerHead.cpp
 *  Copyright 2011 W. Reckman. All rights reserved.
 */
#include "ScoreBoardApp.h"
#include "Settings.h"
#include "PlayerHead.h"

const float PlayerHead::MAX_BITE_ANGLE = 25.0f;


PlayerHead::PlayerHead( ScoreBoardApp& appRef_ )
: s( Settings::getInstance() ), appRef( appRef_ ), moveSpeedFactor( 1.0f ),
  drawingEnabled( false ), pos( 0, 0 ), xDir( true ), yDir( true ),
  drawMirrored( false ), drawRotated( 0.0f )
{}

PlayerHead::~PlayerHead() {
	delete topImage; topImage = 0;
	delete bottomImage; bottomImage = 0;
}

void PlayerHead::setup( const BoardModel::PlayerInfo& info_, int gameNumber_ ) {
	bool rv;
	
	baseMoveSpeed = ofToFloat( *s.getValue( "base_head_speed", "50" ) );
	moveSpeedVariation = ofToFloat( *s.getValue( "head_speed_variation", "0.0f" ) );
	baseBiteSpeed = ofToFloat( *s.getValue( "base_bite_speed", "100" ) );
	
	moveSpeedFactor = ofRandom( 1.0f - moveSpeedVariation, 1.0f + moveSpeedVariation );
	
	info = info_;
	gameNumber = gameNumber_;
	
	topImage = new ofImage();
	rv = topImage->loadImage( *info.topImagePath );
	
	if ( ! rv ) {
		ofLog( OF_LOG_ERROR, "(Player.cpp) could not load top image ('%s')", info.topImagePath->c_str() );
	}
	
	bottomImage = new ofImage();
	rv = bottomImage->loadImage( *info.bottomImagePath );
	
	if ( ! rv ) {
		ofLog( OF_LOG_ERROR, "(Player.cpp) could not load top image ('%s')", info.bottomImagePath->c_str() );
	}
	
	if ( info.cultureTgt + info.industryTgt != 100 ) {
		ofLog( OF_LOG_WARNING, "(Player.cpp) target balance values are incorrect ( %i + %i != 100)", info.cultureTgt, info.industryTgt );
	}
}

void PlayerHead::update() {
	float elapsed = appRef.getBoard().getTime() - lastGameTime;
	
	if ( ! drawingEnabled ) return;
	
	if ( biteAngleIncreasing ) {
		biteAngle += baseBiteSpeed * elapsed;
		if ( biteAngle >= MAX_BITE_ANGLE ) {
			biteAngle = MAX_BITE_ANGLE;
			biteAngleIncreasing = false;
		}
	} else {
		biteAngle -= baseBiteSpeed * elapsed;
		if ( biteAngle <= 0.0f ) {
			biteAngle = 0.0f;
			biteAngleIncreasing = true;
		}
	}
	
	float moveDist = baseMoveSpeed * moveSpeedFactor * elapsed;
	if ( minX < maxX ) {
		pos.x = xDir ? pos.x + moveDist : pos.x - moveDist;
		if ( xDir && pos.x >= maxX ) { pos.x = maxX; xDir = false; }
		else if ( ! xDir && pos.x <= minX ) { pos.x = minX; xDir = true; }
	}
	
	if ( minY < maxY ) {
		pos.y = yDir ? pos.y + moveDist : pos.y - moveDist;
		if ( yDir && pos.y >= maxY ) { pos.y = maxY; yDir = false; }
		else if ( ! yDir && pos.y <= minY ) { pos.y = minY; yDir = true; }
	}
	
	lastGameTime = appRef.getBoard().getTime();
}

//--------------------------------------------------------------
void PlayerHead::drawAtPos( int x_, int y_, float animPos_, float scale_ ) const {
	if ( ! drawingEnabled ) return;
	
	//draw( x_, y_ - appRef.getBoard().getPlayerYSubtract(), drawRotated * ( 1.0f - animPos_ ), scale_ );
	draw( x_, y_, drawRotated * ( 1.0f - animPos_ ), scale_ );
}

//--------------------------------------------------------------
void PlayerHead::draw( bool drawAsWinner_, float animPos_ ) const {
	if ( ! drawingEnabled ) return;
	
	const BoardModel& board = appRef.getBoard();
	if ( ! drawAsWinner_ ) {
		//draw( pos.x, pos.y - board.getPlayerYSubtract(), drawRotated, 1.0f );
		draw( pos.x, pos.y, drawRotated, 1.0f );
	} else {
		ofPoint center( appRef.getCanvasWidth() / 2, appRef.getCanvasHeight() / 2 );
		ofPoint dp = pos + ( center - pos ) * animPos_;
		draw( dp.x, dp.y, drawRotated * ( 1.0f - animPos_ ), 1.0f );
	}
}

//--------------------------------------------------------------
int PlayerHead::getGameNumber() const { return gameNumber; }
const BoardModel::PlayerInfo& PlayerHead::getInfo() const { return info; }

//--------------------------------------------------------------
void PlayerHead::setDrawingEnabled( bool enable_ ) { drawingEnabled = enable_; }
void PlayerHead::setPosition( float x_, float y_ ) { pos.x = x_; pos.y = y_; }
void PlayerHead::setXRange( float minX_, float maxX_ ) { minX = minX_; maxX = maxX_; }
void PlayerHead::setYRange( float minY_, float maxY_ ) { minY = minY_; maxY = maxY_; }
void PlayerHead::setMoveSpeedFactor( float factor_ ) { moveSpeedFactor = factor_; }

/*********************
 * PRIVATE FUNCTIONS *
 *********************/

//--------------------------------------------------------------
void PlayerHead::draw( int x_, int y_, float rotation_, float scale_ ) const {
	static const float drawAlpha = 0.9f;
	static const int drawWidth = 90;
	
	if ( ! drawingEnabled ) return;
	
	//const ofPoint& drawDims = game.getPlayerDrawSize();
	const ofPoint drawDims( drawWidth, drawWidth * ( 3.0f / 4.0f ) );
	float drawW = drawDims.x;
	float drawH = drawDims.y;
	float topDrawH = drawDims.y * BoardModel::PLAYER_TOP_TO_TOTAL_RATIO;
	float bottomDrawH = drawDims.y - drawDims.y * BoardModel::PLAYER_TOP_TO_TOTAL_RATIO;
	//const ofPoint& pos = getPosition();
	//const ofPoint& pos = pos;
	
	ofPushStyle();
	ofPushMatrix();
	
	if ( drawMirrored ) {
		glScalef( -1, 1, 1 );
		ofTranslate( -x_, y_, 0 );
	} else {
		ofTranslate( x_, y_, 0 );
	}
	glScalef( scale_, scale_, scale_ );
	ofRotateZ( rotation_ );
	
	//	if ( appRef.debugDrawingEnabled ) {
//	ofSetColor( info.color.r, info.color.g, info.color.b, 255 * drawAlpha * 0.5f );
//	ofCircle( 0, 0, drawW / 2 );
	//	}
	
	ofSetColor( 255, 255, 255, 255 * drawAlpha );
	
	topImage->draw( -drawW / 2, -drawH / 2, drawW, topDrawH );
	
	ofTranslate( -drawW / 2, drawH / 2 - bottomDrawH, 0 );
	ofRotateZ( biteAngle );
	bottomImage->draw( 0, 0, drawW, bottomDrawH );
	
	ofPopMatrix();
	
	if ( appRef.debugDrawingEnabled ) {
		//GridObject::draw();
	}
	
	ofPopStyle();
}
